package cetc54.zhtx.client;

import cetc54.zhtx.common.ConstantPool;
import cetc54.zhtx.entity.HeartBeat;
import cetc54.zhtx.start.ClientListenStatus;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.NettyRuntime;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 心跳机制-客户端
 *
 * @author lipeng
 */
@Slf4j
public class HeartBeatClient {

    public HeartBeatClient(HeartBeat heartBeat, ClientListenStatus listenStatus){
        this.heartBeat=heartBeat;
        this.listenStatus=listenStatus;
        //初始化
        init();
        //建立连接
        connect();
    }

    /**
     * 事件处理接口
     */
    private ClientListenStatus listenStatus;

    /**
     * 默认连接参数
     */
    private HeartBeat heartBeat;


    private  Bootstrap bootstrap;

    private EventLoopGroup eventExecutors;

    /**
     * 重试计数
     */
    private AtomicInteger atomicInteger=new AtomicInteger();


    /**
     * 绑定ip 与端口
     * @return
     */
    private ChannelFuture bind(){
        return bootstrap.connect(heartBeat.getStandbyIp(), heartBeat.getPort());
    }


    /**
     * 建立连接
     */
    public void connect() {
        try {
            //建立连接
            ChannelFuture future = bind();
            //重连机制 连接失败后，每n秒重试一次 共重试n次
            future.addListener(future1 -> {
                if(future1.isSuccess()){
                    log.info("连接备机服务器成功");
                    atomicInteger.set(0);
                }else{
                    future.channel().eventLoop().schedule(() -> {
                        //若超过配置的次数，且不是永久重试，则退出
                        if (atomicInteger.get() >= heartBeat.getRetryCount()&&heartBeat.getRetryCount()!= ConstantPool.EVERLASTING_CONNECTION) {
                            log.info("重试结束，未连接上备机服务器");
                            return;
                        }
                        connect();
                        log.info("第" +  atomicInteger.incrementAndGet() + "次重试连接备机服务器");
                    }, heartBeat.getRetryFrequency(), TimeUnit.SECONDS);
                }

            });
        } catch (Exception e) {
            log.error("连接服务器错误", e);
            eventExecutors.shutdownGracefully();
        }
    }

    /**
     * 初始化
     */
    private void init() {
        eventExecutors = new NioEventLoopGroup(NettyRuntime.availableProcessors()*2);
        bootstrap = new Bootstrap();
        bootstrap.group(eventExecutors)
                .channel(NioSocketChannel.class)
                .handler(new ClientHeartBeatInitializer(this,listenStatus));
    }


    /**
     * 关闭客户端
     */
    public void stopClient(){
        eventExecutors.shutdownGracefully();
    }


}
